﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ScriptifyLibrary20;
using ScriptifyLibrary40;
using System.Resources;
using System.Reflection;
using PresentationControls;
using System.Xml;

namespace ScriptifyWinForms
{
    public partial class Main : Form
    {
        IScriptifyDataAccess scriptify;
        string _defaultFilter;
        //ResXResourceSet rm;
        
        public Main()
        {
            InitializeComponent();
            _defaultFilter =    "([Schema] <> 'INFORMATION_SCHEMA') AND ([Schema] <> 'sys') AND " +
                                "([Type] IN ('ExtendedStoredProcedure', 'PartitionFunction', 'PartitionScheme', " +
                                "'SqlAssembly', 'StoredProcedure', 'Table', 'Trigger', 'UserDefinedAggregate', " +
                                "'UserDefinedDataType', 'UserDefinedFunction', 'UserDefinedType', 'View'))";

            this.helpProvider1.SetHelpString(this.textBoxFileName, "Enter the name of the single file or the folder where the files we'll be stored. If you want to enter date and time use standard c# notation between '#' i.e. 'myfolder#ddMMyy#' will give a folder or a filename called myfolder221182" );

            // Create a resource manager to retrieve resources.
            //rm = new ResXResourceSet("Properties/Strings.resx");

            statusLabel.Text = "Ready";
            this.comboBoxTechnology.SelectedIndex = 0;
        }


        /// <summary>
        /// This method reacts to a change in database technology and modify the interface accordingly
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBoxTechnology_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch(this.comboBoxTechnology.SelectedIndex)
            {
                case 0:
                    scriptify = new ScriptifySQLServer();
                    labelFind.Enabled = buttonGetObjects.Enabled = buttonGetDBs.Enabled = buttonScript.Enabled = buttonGenerate.Enabled = true;
                    break;
                case 1:
                    scriptify = new ScriptifyOracle();
                    labelFind.Enabled = buttonGetObjects.Enabled = buttonGetDBs.Enabled = buttonScript.Enabled = buttonGenerate.Enabled = false;
                    break;
                case 2:
                    scriptify = new ScriptifySybaseAnywhere();
                    labelFind.Enabled = buttonGetObjects.Enabled = buttonGetDBs.Enabled = buttonScript.Enabled = buttonGenerate.Enabled = true;
                    break;
                default:
                    scriptify = null;
                    labelFind.Enabled = buttonGetObjects.Enabled = buttonGetDBs.Enabled = buttonScript.Enabled = buttonGenerate.Enabled = false;
                    break;
            }
        }


        /// <summary>
        /// This method close the application when the user click on Exit
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }


        /// <summary>
        /// This method shows the About page
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            About a = new About();
            a.ShowDialog();
        }


        /// <summary>
        /// This method shows username/password or not according to Windows Authentication Flag
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void checkBoxWindowsAuth_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxWindowsAuth.Checked)
            {
                labelPassword.Visible = labelUsername.Visible = textBoxUsername.Visible = textBoxPassword.Visible = labelShowHide.Visible = false;
            }
            else
            {
                labelPassword.Visible = labelUsername.Visible = textBoxUsername.Visible = textBoxPassword.Visible = labelShowHide.Visible = true;
            }
        }


        /// <summary>
        /// This method calls the GetServers to populate Server textbox
        /// REMEMBER: Toggle use according to technology
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void labelFind_Click(object sender, EventArgs e)
        {
            statusLabel.Text = "Getting network servers... Please wait.";
            Application.DoEvents();
            comboBoxServers.Items.Clear();
            comboBoxServers.Items.AddRange(scriptify.GetServers().ToArray());
            comboBoxServers.SelectedIndex = 0;
            toolStripProgressBar1.Value = 100;
            statusLabel.Text = "Ready!";
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonGetDBs_Click(object sender, EventArgs e)
        {
            statusLabel.Text = "Getting databases... Please wait.";
            Application.DoEvents();
            comboBoxDatabases.Items.Clear();
            ScriptifyServer ss = new ScriptifyServer() 
            { 
                databaseName = comboBoxDatabases.Text, 
                isWindowsAuthentication = checkBoxWindowsAuth.Checked, 
                serverName = comboBoxServers.Text, 
                username = textBoxUsername.Text, 
                password = textBoxPassword.Text 
            };

            comboBoxDatabases.Items.AddRange(scriptify.GetDatabases(ss, new WinFormProgressBar(toolStripProgressBar1, statusLabel)).ToArray());
            comboBoxDatabases.SelectedIndex = 0;
            statusLabel.Text = "Ready!";
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonGetObjects_Click(object sender, EventArgs e)
        {
            statusLabel.Text = "Getting objects... Please wait.";
            Application.DoEvents();

            ScriptifyServer ss = new ScriptifyServer()
            {
                databaseName = comboBoxDatabases.Text,
                isWindowsAuthentication = checkBoxWindowsAuth.Checked,
                serverName = comboBoxServers.Text,
                username = textBoxUsername.Text,
                password = textBoxPassword.Text
            };

            List<ScriptifyObject> objs = scriptify.GetObjects(ss, new WinFormProgressBar(toolStripProgressBar1, statusLabel));

            dataGridView1.AutoGenerateColumns = true;
            DataTable dt = new DataTable();
            dt.Columns.Add("Script", typeof(Boolean));
            dt.Columns.Add("Schema", typeof(String));
            dt.Columns.Add("Object", typeof(String));
            dt.Columns.Add("Type", typeof(String));
            dt.Columns.Add("URN", typeof(String));

            checkBoxComboBox1.Items.AddRange(objs.AsQueryable().Select(i => i.Schema).Distinct().ToArray());
            checkBoxComboBox2.Items.AddRange(objs.AsQueryable().Select(i => i.ObjectType).Distinct().ToArray());

            foreach (ScriptifyObject obj in objs)
                dt.Rows.Add(false, obj.Schema, obj.ObjectName, obj.ObjectType, obj.URN);

            DataView dv = new DataView(dt);
            dv.Sort = "[Type]";
            dv.RowFilter =  _defaultFilter;
            dataGridView1.DataSource = dv;
            dataGridView1.Columns[1].ReadOnly = true;
            dataGridView1.Columns[2].ReadOnly = true;
            dataGridView1.Columns[3].ReadOnly = true;
            dataGridView1.Columns[4].ReadOnly = true;
            dataGridView1.Columns[4].Visible = false;

            statusLabel.Text = "Ready!";
            tabControl1.SelectedIndex = 1;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonScript_Click(object sender, EventArgs e)
        {
            statusLabel.Text = "Scripting objects... Please wait.";
            Application.DoEvents();

            ScriptifyServer ss = new ScriptifyServer()
            {
                databaseName            = comboBoxDatabases.Text,
                isWindowsAuthentication = checkBoxWindowsAuth.Checked,
                serverName              = comboBoxServers.Text,
                username                = textBoxUsername.Text,
                password                = textBoxPassword.Text
            };

            ScriptifyOptions so = new ScriptifyOptions()
            {
                includeCreates              = checkBoxProps1.Checked,
                includeDrops                = checkBoxProps2.Checked,
                includeKeys                 = checkBoxProps4.Checked,
                includeIndexes              = checkBoxProps5.Checked,
                includeHeaders              = checkBoxProps6.Checked,
                includePermissions          = checkBoxProps7.Checked,
                includeCollation            = checkBoxProps8.Checked,
                qualifySchema               = checkBoxProps9.Checked,
                qualifyForeignKeysSchema    = checkBoxProps9.Checked,
                includeIfNotExists          = checkBoxProps3.Checked,
                isUnicode                   = radioButton2.Checked,
                generateFiles               = !radioButton3.Checked,
                multipleFiles               = radioButton5.Checked,
                namingConvention            = false,
                folderLocation              = textBoxFolderLocation.Text,
                folderNaming                = textBoxFileName.Text
            };

            DataView dv = (DataView)dataGridView1.DataSource;
            dv.RowFilter = "[Script] = True";
            List<ScriptifyObject> objs = new List<ScriptifyObject>();
            foreach (DataRowView r in dv)
            {
                objs.Add(new ScriptifyObject() { Schema = r[1].ToString(), ObjectName = r[2].ToString(), ObjectType = r[3].ToString(), URN = r[4].ToString() });

            }

            StringBuilder sb = scriptify.ScriptDatabase(ss, so, objs, new WinFormProgressBar(toolStripProgressBar1, statusLabel));

            textBoxScript.Text = sb.ToString();

            dv.RowFilter = _defaultFilter;
            statusLabel.Text = "Ready!";
            tabControl1.SelectedIndex = 2;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void checkBoxScriptAll_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox c = (CheckBox)sender;
            foreach (DataGridViewRow r in dataGridView1.Rows)
            {
                r.Cells[0].Value = c.Checked;
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void checkBoxComboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            List<string> ss = new List<string>();
            foreach(CheckBoxComboBoxItem item in checkBoxComboBox1.CheckBoxItems)
            {
                if(item.Checked)
                    ss.Add(item.Text);    
            }

            foreach (DataGridViewRow dr in dataGridView1.Rows)
            {
                if (ss.Contains(dr.Cells[1].Value.ToString()))
                {
                    dr.Cells[0].Value = true;
                }
                else
                {
                    dr.Cells[0].Value = false;
                }
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void checkBoxComboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            List<string> ss = new List<string>();
            foreach (CheckBoxComboBoxItem item in checkBoxComboBox2.CheckBoxItems)
            {
                if (item.Checked)
                    ss.Add(item.Text);
            }

            foreach (DataGridViewRow dr in dataGridView1.Rows)
            {
                if (ss.Contains(dr.Cells[3].Value.ToString()))
                {
                    dr.Cells[0].Value = true;
                }
                else
                {
                    dr.Cells[0].Value = false;
                }
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonFolderLocation_Click(object sender, EventArgs e)
        {
            this.folderBrowserDialog1.ShowNewFolderButton = true;
            this.folderBrowserDialog1.RootFolder = System.Environment.SpecialFolder.MyComputer;
            if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                this.textBoxFolderLocation.Text = this.folderBrowserDialog1.SelectedPath;
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void checkBox3_CheckedChanged(object sender, EventArgs e)
        {
                checkBoxProps1.Checked = checkBox3.Checked;
                checkBoxProps2.Checked = checkBox3.Checked;
                checkBoxProps3.Checked = checkBox3.Checked;
                checkBoxProps4.Checked = checkBox3.Checked;
                checkBoxProps5.Checked = checkBox3.Checked;
                checkBoxProps6.Checked = checkBox3.Checked;
                checkBoxProps7.Checked = checkBox3.Checked;
                checkBoxProps8.Checked = checkBox3.Checked;
                checkBoxProps9.Checked = checkBox3.Checked;
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonClipboard_Click(object sender, EventArgs e)
        {
            textBoxScript.SelectAll();
            textBoxScript.Copy();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonSaveAs_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                System.IO.StreamWriter sw;
                if (radioButton1.Checked)
                    sw = new System.IO.StreamWriter(saveFileDialog1.FileName, false, Encoding.ASCII);
                else
                    sw = new System.IO.StreamWriter(saveFileDialog1.FileName, false, Encoding.Unicode);

                foreach (String str in textBoxScript.Lines)
                {
                    sw.WriteLine(str);
                }

                sw.Close();
            }
        }


        /// <summary>
        /// This method generate an xml to be used in Executable
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonGenerateXML_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                using (XmlWriter writer = XmlWriter.Create(folderBrowserDialog1.SelectedPath + "/ScriptifyConfig.xml"))
                {

                    DataView dv = (DataView)dataGridView1.DataSource;
                    dv.RowFilter = "[Script] = True";
                    List<ScriptifyObject> objs = new List<ScriptifyObject>();
                    foreach (DataRowView r in dv)
                    {
                        objs.Add(new ScriptifyObject() { Schema = r[1].ToString(), ObjectName = r[2].ToString(), ObjectType = r[3].ToString(), URN = r[4].ToString() });

                    }

                   
                    writer.WriteStartDocument();
                    writer.WriteStartElement("ScriptifyConfig");
                    
                    writer.WriteStartElement("ScriptifyOptions");
                    writer.WriteElementString("includeHeaders", (checkBoxProps6.Checked) ? "true" : "false");
                    writer.WriteElementString("includeIndexes", (checkBoxProps5.Checked) ? "true" : "false");
                    writer.WriteElementString("includeKeys", (checkBoxProps4.Checked) ? "true" : "false");
                    writer.WriteElementString("includeCollation", (checkBoxProps8.Checked) ? "true" : "false");
                    writer.WriteElementString("qualifySchema", (checkBoxProps9.Checked) ? "true" : "false");
                    writer.WriteElementString("qualifyForeignKeysSchema", (checkBoxProps9.Checked) ? "true" : "false");
                    writer.WriteElementString("includePermissions", (checkBoxProps7.Checked) ? "true" : "false");
                    writer.WriteElementString("includeDrops", (checkBoxProps2.Checked) ? "true" : "false");
                    writer.WriteElementString("includeCreates", (checkBoxProps1.Checked) ? "true" : "false");
                    writer.WriteElementString("includeIfNotExists", (checkBoxProps3.Checked) ? "true" : "false");
                    writer.WriteElementString("isUnicode", (radioButton2.Checked) ? "true" : "false");
                    writer.WriteElementString("folderLocation", textBoxFolderLocation.Text);
                    writer.WriteElementString("folderNaming", textBoxFileName.Text);
                    writer.WriteElementString("multipleFiles", (radioButton5.Checked) ? "true" : "false");
                    writer.WriteElementString("namingConvention", "true");
                    writer.WriteEndElement();

                    writer.WriteStartElement("ScriptifyServer");
                    writer.WriteElementString("serverName", comboBoxServers.Text);
                    writer.WriteElementString("databaseName", comboBoxDatabases.Text);
                    writer.WriteElementString("username", textBoxUsername.Text);
                    writer.WriteElementString("password", textBoxPassword.Text);
                    writer.WriteElementString("isWindowsAuthentication", (checkBoxWindowsAuth.Checked) ? "true" : "false");
                    writer.WriteEndElement();

                    writer.WriteStartElement("ScriptifyObjects");
                    
                    foreach(ScriptifyObject obj in objs)
                    {
                        writer.WriteStartElement("object");
                        writer.WriteAttributeString("type", obj.ObjectType);
                        writer.WriteAttributeString("schema", obj.Schema);
                        writer.WriteAttributeString("name", obj.ObjectName);
                        writer.WriteAttributeString("URN", obj.URN);
                        writer.WriteEndElement();
                    }

                    writer.WriteEndElement();
                    writer.WriteEndElement();
                    writer.WriteEndDocument();

                    dv.RowFilter = "([Schema] <> 'INFORMATION_SCHEMA') AND ([Schema] <> 'sys')";
                    statusLabel.Text = "Ready!";

                }
            }

        }


        /// <summary>
        /// This method toggle the password visibility
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void labelShowHide_Click(object sender, EventArgs e)
        {
            if (textBoxPassword.PasswordChar == '*')
                textBoxPassword.PasswordChar = '\0';
            else
                textBoxPassword.PasswordChar = '*';
        }

    }
}
